#!/usr/bin/python3.6
# -*- coding: utf-8 -*-
# @Time    : 2024/11/26 11:46
# @Author  : zmz
# @File    : breakeven_analysis.py
# @function: 盈亏平衡分析
# @Software: PyCharm

import PySimpleGUI as sg
import matplotlib

matplotlib.use('TkAgg')  # 或者 'Qt5Agg'
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import numpy as np

'''
核心是确定盈亏平衡点，即企业处于收入等于成本，利润为零的状态。在这个点上，企业既不盈利也不亏损。
从成本角度，企业的成本分为固定成本和可变成本。固定成本不随产量变化，像厂房租金、设备折旧；可变成本随产量变化，如原材料、直接人工。

计算盈亏平衡点有两种常见方法。
一是产量法，盈亏平衡点产量 = 固定成本 ÷（单位售价 - 单位可变成本）。
eg.固定成本是 10000 元，单位售价 10 元，单位可变成本 6 元，盈亏平衡点产量 = 10000÷(10 - 6)=2500 件。

二是销售额法，盈亏平衡点销售额 = 固定成本 ÷（1 - 可变成本率），可变成本率是可变成本占销售收入的百分比。这种方法在考虑多种产品组合销售时更方便。
eg.假设一家企业生产某种产品，固定成本为60000元，单位售价为20元，单位可变成本为12元。
首先计算可变成本率，可变成本率 =（单位可变成本 ÷ 单位售价）× 100% =（12/20）× 100% = 60%。
然后用销售额法计算盈亏平衡点销售额，根据公式盈亏平衡点销售额 = 固定成本 ÷（1 - 可变成本率），
可得盈亏平衡点销售额 = 60000/(1-60%)=150000，这意味着该企业的销售额达到150000元时，正好处于盈亏平衡状态。
'''



# 盈亏平衡分析布局
layout = [
    [sg.Text('总固定成本：', size=(12, 1)), sg.InputText(default_text="82800.00 ", key='total_fixed_cost')
     # ,sg.Text('盈亏平衡点（）：', key='break_even_point_text')
     ],
    [sg.Text('单位变动成本：', size=(12, 1)), sg.InputText(default_text="90.00 ", key='unit_variable_cost'),
     sg.Text('盈亏平衡点（销量）：', key='break_even_point_sales_volume_text')],
    [sg.Text('单位售价：', size=(12, 1)), sg.InputText(default_text="210", key='unit_price'),
     sg.Text('盈亏平衡生产能力利用率：', key='break_even_production_capacity_utilization_text')],
    [sg.Text('销量范围', size=(12, 1)), sg.InputText(default_text="0, 3000, 10", key='sales_volume_range'),
       sg.Text('(起始值,终止值,步长）', size=(20, 1)), ],
    [sg.Button('盈亏平衡分析')],
    # [sg.Text('销售收入：', key='revenue_text')],
    # [sg.Text('总成本：', key='total_cost_text')],
    [sg.Canvas(key='-CANVAS_bpq-')]
]

# 盈亏平衡点分析处理
def  break_handle(window,values):
        try:
            # 获取输入并转换为相应的数据类型
            total_fixed_cost = float(values['total_fixed_cost'])
            unit_variable_cost = float(values['unit_variable_cost'])
            unit_price = float(values['unit_price'])
            sales_volume_range_str = values['sales_volume_range'].split(',')
            sales_volume_start = int(sales_volume_range_str[0].strip())
            sales_volume_end = int(sales_volume_range_str[1].strip())
            sales_volume_step = int(sales_volume_range_str[2].strip())
            # 生成销量值列表
            sales_volume = np.arange(sales_volume_start, sales_volume_end + 1, sales_volume_step)
            # 计算销售收入
            revenue = unit_price * sales_volume
            # 计算总成本
            total_cost = total_fixed_cost + unit_variable_cost * sales_volume
            # 计算利润
            profit = revenue - total_cost
            # 计算盈亏平衡点（产量和销量在这个简单模型中是相同概念，都按照以下公式计算）
            break_even_point = total_fixed_cost / (unit_price - unit_variable_cost)
            # 计算盈亏平衡生产能力利用率
            break_even_production_capacity_utilization = break_even_point / max(sales_volume) * 100
            # 更新界面显示结果
            # window['revenue_text'].update(f'销售收入：{revenue}')
            # window['total_cost_text'].update(f'总成本：{total_cost}')
            # window['break_even_point_text'].update(f'盈亏平衡点（产量）：{break_even_point}')
            window['break_even_point_sales_volume_text'].update(f'盈亏平衡点（销量）：{break_even_point}')
            window['break_even_production_capacity_utilization_text'].update(f'盈亏平衡生产能力利用率（%）：{break_even_production_capacity_utilization:.2f}')
            # 绘制图形
            fig, ax = plt.subplots(figsize=(6, 4))
            ax.plot(sales_volume, revenue, label='Revenue')#销售收入
            ax.plot(sales_volume, total_cost, label='Total Cost')#总成本
            ax.axvline(x=break_even_point, color='r', linestyle='--', label='Break-even Point')#盈亏平衡点
            ax.set_xlabel('Sales Volume')#销量
            ax.set_ylabel('Amount ')#金额
            ax.set_title('Revenue, Total Cost and Break-even Point')#销售收入、总成本与盈亏平衡点
            ax.legend()

            # 将绘制好的图形嵌入到PySimpleGUI的Canvas中
            canvas = window['-CANVAS_bpq-'].TKCanvas
            figure_canvas_agg = FigureCanvasTkAgg(fig, master=canvas)
            figure_canvas_agg.draw()
            figure_canvas_agg.get_tk_widget().config(width=600, height=380)
            figure_canvas_agg.get_tk_widget().pack(side='top', fill='both', expand=1)

        except ValueError:
            sg.popup('请输入正确的数值！')

